﻿namespace FloorPlan
{
    using System;
    using System.IO;

    public class PngEncoder
    {
        private static byte[] _4BYTEDATA = new byte[] { 0, 0, 0, 0 };
        private const int _ADLER32_BASE = 0xfff1;
        private static byte[] _ARGB = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 8, 6, 0, 0, 0 };
        private static uint[] _crcTable = new uint[0x100];
        private static bool _crcTableComputed = false;
        private static byte[] _GAMA = new byte[] { 0x67, 0x41, 0x4d, 0x41 };
        private static byte[] _HEADER = new byte[] { 0x89, 80, 0x4e, 0x47, 13, 10, 0x1a, 10 };
        private static byte[] _IDAT = new byte[] { 0x49, 0x44, 0x41, 0x54 };
        private static byte[] _IEND = new byte[] { 0x49, 0x45, 0x4e, 0x44 };
        private static byte[] _IHDR = new byte[] { 0x49, 0x48, 0x44, 0x52 };
        private const int _MAXBLOCK = 0xffff;

        private static uint ComputeAdler32(byte[] buf)
        {
            uint num3 = 1;
            uint num4 = 0;
            int length = buf.Length;
            int num6 = length - 1;
            for (int i = 0; i <= num6; i++)
            {
                //num3 = ((ulong) (num3 + buf[i])) % 0xfff1L;
                //num4 = ((ulong) (num4 + num3)) % 0xfff1L;
            }
            return ((num4 << 0x10) + num3);
        }

        public static Stream Encode(byte[] data, int width, int height)
        {
            uint num2;
            MemoryStream stream3 = new MemoryStream();
            //stream3.Write(_HEADER, 0, _HEADER.Length);
            //byte[] bytes = BitConverter.GetBytes(width);
            //_ARGB[0] = bytes[3];
            //_ARGB[1] = bytes[2];
            //_ARGB[2] = bytes[1];
            //_ARGB[3] = bytes[0];
            //bytes = BitConverter.GetBytes(height);
            //_ARGB[4] = bytes[3];
            //_ARGB[5] = bytes[2];
            //_ARGB[6] = bytes[1];
            //_ARGB[7] = bytes[0];
            //WriteChunk(stream3, _IHDR, _ARGB);
            //bytes = BitConverter.GetBytes(0x186a0);
            //_4BYTEDATA[0] = bytes[3];
            //_4BYTEDATA[1] = bytes[2];
            //_4BYTEDATA[2] = bytes[1];
            //_4BYTEDATA[3] = bytes[0];
            //WriteChunk(stream3, _GAMA, _4BYTEDATA);
            //uint num8 = (width * 4) + 1L;
            //uint num4 = num8 * height;
            //uint num = ComputeAdler32(data);
            //MemoryStream stream = new MemoryStream();
            //uint num7 = 0xffffL / ((ulong) num8);
            //uint num3 = num7 * num8;
            //uint num6 = num4;
            //if ((num4 % num3) == 0L)
            //{
            //    num2 = num4 / num3;
            //}
            //else
            //{
            //    num2 = (num4 / num3) + 1L;
            //}
            //stream.WriteByte(120);
            //stream.WriteByte(0xda);
            //uint num10 = num2 - 2L;
            //for (uint i = 0; i <= num10; i++)
            //{
            //    ushort num5 = (num6 < num3) ? ((ushort) num6) : ((ushort) num3);
            //    if (num5 == num6)
            //    {
            //        stream.WriteByte(1);
            //    }
            //    else
            //    {
            //        stream.WriteByte(0);
            //    }
            //    stream.Write(BitConverter.GetBytes(num5), 0, 2);
            //    stream.Write(BitConverter.GetBytes(~num5), 0, 2);
            //    stream.Write(data, (int) (i * num3), num5);
            //    num6 -= num3;
            //}
            //WriteReversedBuffer(stream, BitConverter.GetBytes(num));
            //stream.Seek(0L, 0);
            //byte[] buffer = new byte[(stream.Length - 1L) + 1];
            //stream.Read(buffer, 0, (int) stream.Length);
            //WriteChunk(stream3, _IDAT, buffer);
            //WriteChunk(stream3, _IEND, new byte[0]);
            //stream3.Seek(0L, 0);
            return stream3;
        }

        private static uint GetCRC(byte[] buf)
        {
            return (UpdateCRC(uint.MaxValue, buf, buf.Length) ^ uint.MaxValue);
        }

        private static void MakeCRCTable()
        {
            int num4;
            uint index = 0;
            do
            {
                uint num = index;
                int num3 = 0;
                do
                {
                    if ((num & 1L) > 0L)
                    {
                        num = 0xedb88320 ^ (num >> 1);
                    }
                    else
                    {
                        num = num >> 1;
                    }
                    num3++;
                    num4 = 7;
                }
                while (num3 <= num4);
                _crcTable[index] = num;
                index++;
                num4 = 0xff;
            }
            while (index <= num4);
            _crcTableComputed = true;
        }

        private static uint UpdateCRC(uint crc, byte[] buf, int len)
        {
            uint num = crc;
            if (!_crcTableComputed)
            {
                MakeCRCTable();
            }
            int num4 = len - 1;
            for (int i = 0; i <= num4; i++)
            {
                num = _crcTable[(int) ((num ^ buf[i]) & 0xffL)] ^ (num >> 8);
            }
            return num;
        }

        private static void WriteChunk(Stream stream, byte[] type, byte[] data)
        {
            int num;
            int length = type.Length;
            byte[] buf = new byte[(type.Length + (data.Length - 1)) + 1];
            int num3 = type.Length - 1;
            for (num = 0; num <= num3; num++)
            {
                buf[num] = type[num];
            }
            int num4 = data.Length - 1;
            for (num = 0; num <= num4; num++)
            {
                buf[num + length] = data[num];
            }
            WriteReversedBuffer(stream, BitConverter.GetBytes(data.Length));
            stream.Write(buf, 0, buf.Length);
            WriteReversedBuffer(stream, BitConverter.GetBytes(GetCRC(buf)));
        }

        private static void WriteReversedBuffer(Stream stream, byte[] data)
        {
            int length = data.Length;
            byte[] buffer = new byte[(length - 1) + 1];
            int num3 = length - 1;
            for (int i = 0; i <= num3; i++)
            {
                buffer[i] = data[(length - i) - 1];
            }
            stream.Write(buffer, 0, length);
        }
    }
}

